'''
Created on 28 janv. 2011

@author: paraita
'''

from math import pi,sin,cos
import numpy
import math



class Signal(object):
    '''
    classe a heriter qui ne fournit que les parametres de base d'un signal
    '''
    def __init__(self, amplitude, frequence, samples, n):
        '''
        samples: nb samples
        n: nb de samples par periode 
        '''
        self.amplitude = amplitude
        self.frequence = frequence
        self.samples = samples
        self.n = n
        
class Sinusoide(Signal):
    '''
    signal sinusoidal:
    Create a synthetic 'sine wave' with 
    frequency frequence
    N samples
    and n is the number of samples by period >=2
    '''
    x = []
    y = []
    
    def __init__(self, amplitude=1, phase=0, frequence=440.0, samples=100, n=30):
        '''
        constructeur de signal sinusoidal:
        la courbe est construite lors de la creation de ce signal
        '''
        super(Sinusoide, self).__init__(amplitude, frequence, samples, n)
        #print 'Sinusoide: amplitude=',amplitude,' frequence=',frequence,' samples=',samples,' n=',n,' phase=',phase
        self.phase = phase
        self.calculate()
    
    def calculate(self):                
        '''
        calcule une representation du signal et la garde en memoire
        '''
        T = 1.0/self.frequence
        omega = (2*pi)/T
        te= T/self.n
        sig_t = []
        sig_s = []
        for i in range(self.samples):
            t = i*te
            sig_t.append(t)
            sig_s.append(self.amplitude*cos((omega*t)+self.phase))
        
        # Faire un tableau a partir d'une liste    
        self.x = numpy.array(sig_t)
        self.y = numpy.array(sig_s)
        return self
    
    def calculateCourbe(self):                
        '''
        calcule la courbe du signal et la garde en memoire
        '''
        self.x = numpy.arange(self.n)
        self.y = self.amplitude * numpy.cos(2 * numpy.pi * self.frequence * self.x)
        return self
    
    def getValues(self):
        '''
        retourne le couple de tableau x et y pour l'affichage de ce signal
        '''
        return self.x, self.y

class Square(Signal):
    '''
    signal carre:
    Create a synthetic 'square wave' with 
    frequency frequence
    N samples
    and n is the number of samples by period >=2
    '''
    x = []
    y = []
    
    def __init__(self, amplitude=2, r=0.5, frequence=440.0, samples=1000, n=30):
        '''
        constructeur de signal carre
        '''
        super(Square, self).__init__(amplitude, frequence, samples, n)
        #print 'Square: amplitude=',amplitude,' frequence=',frequence,' samples=',samples,' n=',n,' r=',r
        self.r = r
        self.calculate()
        
    def calculate(self):
        '''
        calcule la courbe du signal et la garde en memoire
        '''
        sig_t = []
        sig_s = []
    
        T = 1.0/self.frequence
        te= T/self.n       # Sampling period
    
        for i in range(self.samples):
            t = i*te
            sig_t.append(t)
            if ((i%self.n)<(self.n*self.r)):
                sig_s.append(+self.amplitude)
            else:
                sig_s.append(-self.amplitude)
        
        # Faire un tableau a partir d'une liste    
        self.x = numpy.array(sig_t)
        self.y = numpy.array(sig_s)
            
    def getValues(self):
        '''
        retourne le couple de tableau x et y pour l'affichage de ce signal
        '''
        return self.x, self.y

class Saw(Signal):
    '''
    signal en scie:
    http://en.wikipedia.org/wiki/Sawtooth_wave
    Create a synthetic 'saw wave' with 
    amplitude amplitude
    frequency frequence
    N samples
    and n is the number of samples by period >=2
    '''
    x = []
    y = []
    
    def __init__(self, amplitude=1, frequence=440.0, samples=100, n=30):
        '''
        constructeur de signal en scie
        '''
        super(Saw, self).__init__(amplitude, frequence, samples, n)
        #print 'Saw: amplitude=',amplitude,' frequence=',frequence,' samples=',samples,' n=',n
        self.calculate()
        
    def calculate(self):
        '''
        calcule la courbe du signal et la garde en memoire
        '''
        self.x = numpy.zeros(self.samples,dtype=numpy.float32)
        self.y = numpy.zeros(self.samples,dtype=numpy.float32)
    
        T = 1.0/self.frequence
        te= T/self.n       # Sampling period
    
        for i in range(self.samples): 
            t = i*te
            self.x[i] = t
            self.y[i] =  2*self.amplitude*(t/T - math.floor((t/T)) -0.5)
            
    def getValues(self):
        '''
        retourne le couple de tableau x et y pour l'affichage de ce signal
        '''
        return self.x, self.y

class Triangle(Signal):
    """
    signal triangle:
    http://en.wikipedia.org/wiki/Triangle_wave
    Create a synthetic 'triangle wave' with 
    amplitude amplitude
    frequency frequence
    N samples
    and n is the number of samples by period >=2
    """
    x = []
    y = []
    
    def __init__(self, amplitude=3, frequence=200.0, samples=60, n=50, phase=1.5, offset=-0.0012):
        '''
        constructeur de signal en scie
        '''
        super(Triangle, self).__init__(amplitude, frequence, samples, n)
        #print 'Triangle: amplitude=',amplitude,' frequence=',frequence,' samples=',samples,' n=',n,' phase=',phase,' offset=',offset
        self.offset = offset
        self.phase = phase
        self.calculate()
        
    def calculate(self):
        '''
        calcule la courbe du signal et la garde en memoire
        '''
        self.x = numpy.zeros(self.samples,dtype=numpy.float32)
        self.y = numpy.zeros(self.samples,dtype=numpy.float32)
        
        T = 1.0/self.frequence
        te = T/self.n
        cheat = Saw(self.amplitude, self.frequence, self.samples, self.n)
        res_saw = cheat.getValues()
        for i in range(self.samples): 
            t = i*te
            self.x[i] = t + self.offset
            self.y[i] = -math.fabs(res_saw[1][i]) + self.phase
            
    def getValues(self):
        '''
        retourne le couple de tableau x et y pour l'affichage de ce signal
        '''
        return self.x, self.y
